This script carries out the beta diversity analyses (community composition and structure) for the 2016 Cork great tit microbiome data.

Overall plan" * model 1: all variables of interest, nest as blocking factor * model 2: all variables of interest but age-habitat interaction, nest blocking * model 3: adult samples, all variables of interest, nest blocking * then check are results different when individuals w/ 2 samples are dropped

Gabrielle says not to remove individuals sampled twice

Set-up and libraries

library(devtools)
Loading required package: usethis

Attaching package: ‘devtools’

The following object is masked from ‘package:permute’:

    check
install_github("pmartinezarbizu/pairwiseAdonis/pairwiseAdonis")
Skipping install of 'pairwiseAdonis' from a github remote, the SHA1 (ece560d2) has not changed since last install.
  Use `force = TRUE` to force installation
phyloseq-class experiment-level object
otu_table()   OTU Table:         [ 54343 taxa and 246 samples ]
sample_data() Sample Data:       [ 246 samples by 50 sample variables ]
tax_table()   Taxonomy Table:    [ 54343 taxa by 7 taxonomic ranks ]
refseq()      DNAStringSet:      [ 54343 reference sequences ]

Data cleaning

Remove individuals measured twice * set.seed so same individuals dropped * no adults measured twice

#n_occur <- data.frame(table(metadata.NoDups$bird.ID))
#n_occur[n_occur$Freq > 1,]

set.seed(1189)
metadata.NoDups <- metadata %>% 
    group_by(bird.ID) %>%
    sample_n(1)

dropped.samples <- setdiff(metadata$BIOM.ID, metadata.NoDups$BIOM.ID)

# metadata.even <- metadata %>% 
#     group_by(bird.ID) %>%
#     sample_n(min(table(metadata$bird.ID)))

table(metadata$ageBinned)

1week 2week adult 
   81   114    51 
table(metadata.NoDups$ageBinned)

1week 2week adult 
   55    91    51 

Do i need to scale numeric variables?

numeric.predictors <- c("QubitDNA","Tarsus","Weight", "wing", "broodSizeWhenSampled", "broodSizeMax", "totalFledge", "clutchSize", "layDateFirst", "numberDeadPreRinged", "numberDeadPostRinged","scaled.mass","scaled.mass.wing.adult", "scaled.mass.tarsus.adult","scaled.mass.chick", "scaled.mass.tarsus", "scaled.mass.wing", "DistanceToEdge")

# centre and scale numeric variables ie. subtract mean and divide by st. deviation
metadata.NoDups.scaled <- metadata.NoDups
Error: object 'metadata.NoDups' not found

All birds: CoDa, w/ duplicates

Compositional method, use clr transform

Keeping repeated measures here but using blocking factor to control for repeated samples.

# Filter rare taxa
phylo.knowles <- filter_taxa(phylo.spring, function(x) sum(x > 1) > (0.05*length(x)), TRUE)
# phylo.knowles.clr <- phylo.knowles
# phylo.knowles.clr@otu_table <- otu_table(clr(phylo.knowles@otu_table), taxa_are_rows = F)
# aitchison.dist.dups <- phyloseq::distance(phylo.knowles.clr, method = "euclidean")
pk.otu.clr.dups <- clr(phylo.knowles@otu_table)
aitchison.dist.dups <- vegdist(pk.otu.clr.dups, method = "euclid")
# phylo.TSS <- transform_sample_counts(phylo.knowles, function(x) x/sum(x)) # normalise read counts w/ Total-Sum Scaling
# 
# BCdist <- phyloseq::distance(phylo.TSS, method="bray")

All variables except for habitat have heterogenous dispersions

## H0= No difference in dispersion between groups
# calc dispersion, using distance measure

variables <- c("ageBinned", "habitat", "layDateFirst", "broodSizeWhenSampled", "DistanceToEdge", "SequencePlate")

for(i in variables){ # works
  dispersion <- betadisper(aitchison.dist.dups, metadata.scaled[,i])  #, bias.adjust = T
  print(i) # print variable being tested
  print(permutest(dispersion, pairwise=FALSE, permutations=1000))
  cat("\n") # print line break, makes it easier to read
}
#hist(metadata$layDateFirst)
#ist(sqrt(metadata$DistanceToEdge))

dispersion1 <- betadisper(aitchison.dist.dups, metadata$ageBinned)  #, bias.adjust = T
print(permutest(dispersion1, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df Sum Sq Mean Sq      F N.Perm  Pr(>F)  
Groups      2  107.0    53.5 3.7152   1000 0.02498 *
Residuals 243 3499.2    14.4                        
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
dispersion2 <- betadisper(aitchison.dist.dups, metadata$habitat)  #, bias.adjust = T
print(permutest(dispersion2, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df Sum Sq Mean Sq      F N.Perm Pr(>F)
Groups      1    5.7  5.7331 0.3846   1000 0.5504
Residuals 244 3637.6 14.9082                     
dispersion3 <- betadisper(aitchison.dist.dups, (metadata$layDateFirst))  #, bias.adjust = T
print(permutest(dispersion3, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df Sum Sq Mean Sq      F N.Perm   Pr(>F)    
Groups     27 1047.2  38.785 2.6146   1000 0.000999 ***
Residuals 218 3233.8  14.834                           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
dispersion4 <- betadisper(aitchison.dist.dups, metadata$broodSizeWhenSampled)  #, bias.adjust = T
print(permutest(dispersion4, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df Sum Sq Mean Sq     F N.Perm  Pr(>F)  
Groups      6  220.0  36.674 2.505   1000 0.02498 *
Residuals 239 3499.1  14.641                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
dispersion5 <- betadisper(aitchison.dist.dups, (metadata$DistanceToEdge))  #, bias.adjust = T
print(permutest(dispersion5, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df Sum Sq Mean Sq      F N.Perm   Pr(>F)    
Groups     60 2515.5  41.924 4.0906   1000 0.000999 ***
Residuals 185 1896.0  10.249                           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
dispersion6 <- betadisper(aitchison.dist.dups, metadata$SequencePlate)  #, bias.adjust = T
print(permutest(dispersion6, pairwise=FALSE, permutations=1000))

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 1000

Response: Distances
           Df  Sum Sq Mean Sq      F N.Perm   Pr(>F)    
Groups      4  541.68 135.419 10.509   1000 0.000999 ***
Residuals 241 3105.49  12.886                           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
TukeyHSD(dispersion1)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = distances ~ group, data = df)

$group
                  diff       lwr        upr     p adj
2week-1week -1.4854366 -2.785847 -0.1850262 0.0205827
adult-1week -1.1177060 -2.717328  0.4819163 0.2277401
adult-2week  0.3677306 -1.139788  1.8752487 0.8334642
TukeyHSD(dispersion2)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = distances ~ group, data = df)

$group
                       diff        lwr      upr     p adj
deciduous-conifer 0.3765808 -0.8195671 1.572729 0.5357527
#TukeyHSD(dispersion3)
#TukeyHSD(dispersion4)
#TukeyHSD(dispersion5)

Plot dispersions

perms.dups <- with(metadata, how(nperm = 1000, blocks = nest))

all.adonis.dups.fixed <- adonis2(aitchison.dist.dups ~ ageBinned + habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, by="margin", method="euclidian", data = metadata.scaled, permutations = perms.dups)
pairwiseAdonis::pairwise.adonis2(aitchison.dist.dups ~ ageBinned + habitat, data = metadata.scaled)
$parent_call
[1] "aitchison.dist.dups ~ ageBinned + habitat , strata = Null , permutations 999"

$`2week_vs_adult`
           Df SumOfSqs      R2      F Pr(>F)    
ageBinned   1      647 0.01699 2.8293  0.001 ***
habitat     1      395 0.01036 1.7263  0.001 ***
Residual  162    37034 0.97265                  
Total     164    38075 1.00000                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

$`2week_vs_1week`
           Df SumOfSqs      R2      F Pr(>F)    
ageBinned   1      635 0.01317 2.5796  0.001 ***
habitat     1      335 0.00695 1.3625  0.027 *  
Residual  192    47228 0.97988                  
Total     194    48198 1.00000                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

$adult_vs_1week
           Df SumOfSqs      R2      F Pr(>F)    
ageBinned   1      563 0.01645 2.1756  0.001 ***
habitat     1      270 0.00788 1.0425  0.365    
Residual  129    33369 0.97566                  
Total     131    34201 1.00000                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

attr(,"class")
[1] "pwadstrata" "list"      
#?pairwise.adonis2()

Try same as above but strata by sequence plate and then inlcude individual ID

# perms.dups <- with(metadata, how(nperm = 1000, blocks = SequencePlate))
# 
# all.adonis.dups.fixed <- adonis2(aitchison.dist.dups ~ ageBinned + habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + bird.ID, by="margin", method="euclidian", data = metadata.scaled, permutations = perms.dups)
# 
# all.adonis.dups.fixed

Including bird.ID as a fixed effect and blocking by nest suggests age is in fact a significant factor though accounts for only 0.7% of variation, while bird id accounts for 75%, but is non-significant. Sequence plate is significant, accounting for 2.5%, brood size is not significant while habitat, lay date and distance to edge could not be estimated.

# perms.dups <- with(metadata, how(nperm = 1000, blocks = nest))
# 
# all.adonis.dups.fixed <- adonis2(aitchison.dist.dups ~ ageBinned + habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate + bird.ID, by="margin", method="euclidian", data = metadata.scaled, permutations = perms.dups)
# 
# all.adonis.dups.fixed
# perms.dups <- with(metadata, how(nperm = 1000, blocks = bird.ID))
# 
# all.adonis.dups.fixed <- adonis2(aitchison.dist.dups ~ ageBinned + habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, by="margin", method="euclidian", data = metadata.scaled, permutations = perms.dups)
# 
# all.adonis.dups.fixed
perms.dups <- with(metadata, how(nperm = 1000, blocks = nest))

all.adonis.dups.int <- adonis2(aitchison.dist.dups ~ ageBinned*habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, by="margin", data = metadata.scaled, permutations = perms.dups) #
all.adonis.dups.int
Permutation test for adonis under reduced model
Marginal effects of terms
Blocks:  nest 
Permutation: free
Number of permutations: 1000

adonis2(formula = aitchison.dist.dups ~ ageBinned * habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, data = metadata.scaled, permutations = perms.dups, by = "margin")
                      Df SumOfSqs      R2      F   Pr(>F)    
layDateFirst           1      420 0.00693 1.8300 0.089910 .  
broodSizeWhenSampled   1      305 0.00504 1.3312 0.016983 *  
DistanceToEdge         1      502 0.00830 2.1901 0.000999 ***
SequencePlate          4     3634 0.06002 3.9609 0.000999 ***
ageBinned:habitat      2      595 0.00982 1.2960 0.010989 *  
Residual             233    53444 0.88259                    
Total                245    60554 1.00000                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Interaction calc by term rather than margin to get estimates for main effects as well as interaction term

perms.dups <- with(metadata, how(nperm = 1000, blocks = nest))

adonis2(aitchison.dist.dups ~ ageBinned*habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, by="term", data = metadata.scaled, permutations = perms.dups) #
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Blocks:  nest 
Permutation: free
Number of permutations: 1000

adonis2(formula = aitchison.dist.dups ~ ageBinned * habitat + layDateFirst + broodSizeWhenSampled + DistanceToEdge + SequencePlate, data = metadata.scaled, permutations = perms.dups, by = "term")
                      Df SumOfSqs      R2      F   Pr(>F)    
ageBinned              2     1239 0.02046 2.7003 0.000999 ***
habitat                1      347 0.00573 1.5124 0.000999 ***
layDateFirst           1      490 0.00810 2.1377 0.000999 ***
broodSizeWhenSampled   1      311 0.00514 1.3578 0.078921 .  
DistanceToEdge         1      475 0.00784 2.0689 0.000999 ***
SequencePlate          4     3653 0.06033 3.9816 0.000999 ***
ageBinned:habitat      2      595 0.00982 1.2960 0.009990 ** 
Residual             233    53444 0.88259                    
Total                245    60554 1.00000                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

check influence of unbalanced design

table(metadata$ageBinned, metadata$habitat)
       
        conifer deciduous
  1week      16        65
  2week      27        87
  adult       8        43

For loop sample equal numbers of from each habitat and age combination

Plot PCA

aitch.pca <- prcomp(aitchison.dist.dups)
#plot(aitch.pca)
biplot(aitch.pca)


autoplot(aitch.pca, data = metadata)#, colour = "ageBinned", loadings = T, loadings.label = T, scale = 0)

Code from: https://huboqiang.cn/2016/03/03/RscatterPlotPCA

df_out <- as.data.frame(aitch.pca$x)
df_out$ageBinned <- metadata$ageBinned
df_out$habitat <- metadata$habitat
df_out$layDateFirst <- metadata$layDateFirst
df_out$broodSizeWhenSampled <- metadata$broodSizeWhenSampled

head(df_out)

Calculate the PC loadings for labels * took these from different sites and they disagree alot

# Sum the total variance
d.mvar <- sum(aitch.pca$sdev^2)
# Calculate the PC1 and PC2 variance
PC1.label <- paste("PC1: ", round(sum(aitch.pca$sdev[1]^2)/d.mvar, 3)*100,"%")
PC2.label <- paste("PC2: ", round(sum(aitch.pca$sdev[2]^2)/d.mvar, 3)*100,"%")

#percentage <- round(aitch.pca$sdev / sum(aitch.pca$sdev) * 100, 2)
#percentage <- paste( colnames(df_out), "(", paste( as.character(percentage), "%", ")", sep="") )

#screeplot(aitch.pca)

Plot * Use same name and label for fill and shape in order to overlap legends * ellipse default is 95% confidence level for t distribution * can draw euclid ellipse where level = radius, but how to choose radius? * alpha specifies the transparency * https://stats.stackexchange.com/questions/217374/real-meaning-of-confidence-ellipse

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=ageBinned ))
p <- p + geom_point(aes(shape = habitat)) + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="t", alpha=0.1, 
                      aes(group = interaction(ageBinned, habitat), fill = habitat, colour = ageBinned))
p <- p + scale_fill_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_shape_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_color_discrete(name = "Age", labels = c("Day 8", "Day 15", "Adult"))
#p <- p + scale_shape_discrete(element_blank())#, labels = NULL)
#p + facet_grid(habitat~.)

#theme<-theme(panel.background = element_blank(), panel.border=element_rect(fill=NA), panel.grid.major = element_blank(), panel.grid.minor = element_blank(),strip.background=element_blank(), axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"), axis.ticks=element_line(colour="black"), plot.margin=unit(c(1,1,1,1),"line"))

p+theme_classic()

Try euclidian ellipses, specify radius with level

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=ageBinned ))
p <- p + geom_point(aes(shape = habitat)) + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="euclid", alpha=0.1,level = 10,
                      aes(group = interaction(ageBinned, habitat), fill = habitat, colour = ageBinned))
p <- p + scale_fill_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_shape_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_color_discrete(name = "Age", labels = c("Day 8", "Day 15", "Adult"))
#p <- p + scale_shape_discrete(element_blank())#, labels = NULL)
#p + facet_grid(habitat~.)

#theme<-theme(panel.background = element_blank(), panel.border=element_rect(fill=NA), panel.grid.major = element_blank(), panel.grid.minor = element_blank(),strip.background=element_blank(), axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"), axis.ticks=element_line(colour="black"), plot.margin=unit(c(1,1,1,1),"line"))

p+theme_classic()

facet.labels <- c("Conifer", "Deciduous")
names(facet.labels) <- c("conifer", "deciduous")
p + theme_classic() + facet_grid(habitat~., labeller = labeller(habitat = facet.labels))

# plot_ordination(phylo.TSS, ordBC, color = "ageBinned") + 
#   geom_point(size=3) + 
#   ggtitle("Ord: Bray-Curtis") + stat_ellipse(geom = "polygon", type="t", alpha=0.1, aes(fill=ageBinned))+ 
#   theme_bw() +  theme(panel.grid.major = element_blank(),
#                       panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), 
#                       panel.border = element_rect(linetype = "solid", colour = "black", size=.8)) +
#                       theme(text=element_text(size=14,  family="serif"), axis.ticks = element_line(colour = "black", size = .7))+
#                       geom_point()

Plot features that contribute to classification

df_out_r <- as.data.frame(aitch.pca$rotation)
df_out_r$feature <- row.names(df_out_r)
df_out_r$ageBinned <- metadata$ageBinned
df_out_r$habitat <- metadata$habitat
df_out_r$layDateFirst <- metadata$layDateFirst
df_out_r$broodSizeWhenSampled <- metadata$broodSizeWhenSampled
df_out_r$DistanceToEdge <- metadata$DistanceToEdge


df_out_r

p<-ggplot(df_out_r,aes(x=PC1,y=PC2,label=ageBinned,color=habitat ))
#p<-p+geom_point()+theme + geom_text(size=3) + theme(legend.position = "none")
p

Plot one plot for each habitat ((ellipses each age) * change aplha to 0.05?

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=ageBinned ))
p <- p + geom_point() + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="t", alpha=0.1, 
                      aes(group = interaction(ageBinned), fill = ageBinned, colour = ageBinned))
p <- p + scale_color_discrete(name = "Age", labels = c("Day 8", "Day 15", "Adult"))
p <- p + scale_fill_discrete(element_blank(), labels = NULL)
#p + facet_grid(habitat~.)

p+theme_classic()

facet.labels <- c("Conifer", "Deciduous")
names(facet.labels) <- c("conifer", "deciduous")
p + theme_classic() + facet_grid(habitat~., labeller = labeller(habitat = facet.labels))

one plot for each age (ellipses each habitat)

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=habitat ))
p <- p + geom_point() + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="t", alpha=0.1, 
                      aes(group = (habitat), fill = habitat, colour = habitat))
p <- p + scale_color_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_fill_discrete(element_blank(), labels = NULL)
#p + facet_grid(habitat~.)

p+theme_classic()

facet.labels <- c("Day 8", "Day 15", "Adult")
names(facet.labels) <- c("1week", "2week", "adult")
p + theme_classic() + facet_grid(ageBinned~., labeller = labeller(ageBinned = facet.labels))

JQ requested plots

ellipses for just age

one plot for each age (ellipses each habitat)

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=ageBinned ))
p <- p + geom_point() + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="t", alpha=0.1, 
                      aes(group = (ageBinned), fill = ageBinned, colour = ageBinned))
p <- p + scale_color_discrete(name = "Age", labels = c("D8", "D15", "Adult"))
p <- p + scale_fill_discrete(element_blank(), labels = NULL)
#p + facet_grid(habitat~.)

p+theme_classic()

ellipses for just habitat

p <- ggplot(df_out,aes(x=PC1,y=PC2, color=habitat ))
p <- p + geom_point() + xlab(PC1.label) + ylab(PC2.label) #, show.legend = F
p <- p + stat_ellipse(geom = "polygon", type="t", alpha=0.1, 
                      aes(group = (habitat), fill = habitat, colour = habitat))
p <- p + scale_color_discrete(name = "Habitat", labels = c("Conifer", "Deciduous"))
p <- p + scale_fill_discrete(element_blank(), labels = NULL)
#p + facet_grid(habitat~.)

p+theme_classic()


p.habitat <- p

Combine age and habitat plots

  theme_bw(base_size = base_size, base_family = base_family) %+replace%
    theme(
      legend.position = "none",
      panel.border     = element_blank(),
      axis.line        = element_line(colour = "black"),
      panel.grid.major=element_line(colour="grey", size=0.5, 3),
      panel.grid.major.x = element_blank(),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      panel.grid.minor.x = element_blank(),
      panel.grid.minor.y = element_blank(),
      strip.background = element_blank(),
      legend.key       = element_blank(),
      plot.title = element_text(hjust = 0.5, face = "bold") # centre and bold title
    )
Error in theme_grey(base_size = base_size, base_family = base_family,  : 
  object 'base_size' not found

brood size

envfit1 <- envfit(aitch.pca,metadata$broodSizeWhenSampled, main="", col="red")
#plot(aitch.pca, type = "n")
plot(envfit1)
Error in strwidth(labels, ...) : plot.new has not been called yet

Smooth surface/surf plot

# from Jennys email + https://chrischizinski.github.io/rstats/ordisurf/
species.scores <- as.data.frame(scores(aitch.pca, "species")) # have to keep species here as the taxa
Error in names(x) <- paste("V", seq_along(x), sep = "") : 
  'names' attribute [1] must be the same length as the vector [0]

https://userweb.eng.gla.ac.uk/umer.ijaz/bioinformatics/ecological.html

#p<-p+theme(legend.key = element_blank(),  #removes the box around each legend item
#              legend.position = "bottom", #legend at the bottom
#              legend.direction = "horizontal",
#              legend.box = "horizontal",
#              legend.box.just = "centre")
p
Error in rep(x[[i]], n) : 
  attempt to replicate an object of type 'closure'

Adult birds: CoDa

Aitchison distance is supposedly robust to subsetting- can i therefore just subset the adult birds from previous distance calculation?

phylo.kn.adult <- filter_taxa(phylo.adults, function(x) sum(x > 1) > (0.05*length(x)), TRUE)

# phylo.TSS.adults <- transform_sample_counts(phylo.kn.adult, function(x) x/sum(x))
# 
# BCdist.adults <- phyloseq::distance(phylo.TSS.adults, method="bray")
# JDdist.adults <- phyloseq::distance(phylo.TSS.adults, method="jaccard")
pk.otu.clr.adult <- clr(phylo.kn.adult@otu_table)
aitchison.dist.adult <- vegdist(pk.otu.clr.adult, method = "euclidean")

Check dispersion

Homogenous dispersion: sex, habitat, distance is almost non-homo Non-homogenous: ageDays, …all others

## H0= No difference in dispersion between groups
# calc dispersion, using distance measure

variables <- c("ageDays", "Sex", "habitat", "layDateFirst", "broodSizeWhenSampled", "DistanceToEdge", "SequencePlate")

for(i in variables){ # works
  dispersion <- betadisper(aitchison.dist.adult, adults.meta.scaled[,i])
  print(i) # print variable being tested
  print(permutest(dispersion, pairwise=FALSE, permutations=1000))
  cat("\n") # print line break, makes it easier to read
}

Modelling: adult aitchison

Sex * habitat * broodSizeWhenSampled + Sex * habitat * layDateFirst + habitat * DistanceToEdge + (1|nest) + (1|SequencePlate)

perms.adult <- with(adults.meta, how(nperm = 1000, blocks = nest))

adult.adonis <- adonis2(aitchison.dist.adult ~ ageDays + Sex + habitat + DistanceToEdge + layDateFirst + broodSizeWhenSampled + SequencePlate, by = "margin", data = adults.meta.scaled, permutations = perms.adult)
adult.adonis
Permutation test for adonis under reduced model
Marginal effects of terms
Blocks:  nest 
Permutation: free
Number of permutations: 1000

adonis2(formula = aitchison.dist.adult ~ ageDays + Sex + habitat + DistanceToEdge + layDateFirst + broodSizeWhenSampled + SequencePlate, data = adults.meta.scaled, permutations = perms.adult, by = "margin")
                     Df SumOfSqs      R2      F   Pr(>F)   
ageDays               1    271.0 0.01968 1.0475 0.629371   
Sex                   1    213.0 0.01546 0.8231 0.844156   
habitat               1    290.3 0.02108 1.1221 0.449550   
DistanceToEdge        1    327.0 0.02375 1.2640 0.315684   
layDateFirst          1    323.6 0.02350 1.2507 0.145854   
broodSizeWhenSampled  1    223.3 0.01621 0.8631 0.001998 **
SequencePlate         3   1462.1 0.10616 1.8836 0.003996 **
Residual             41  10608.1 0.77026                   
Total                50  13772.1 1.00000                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#adonis2(JDdist.adults ~ Sex + habitat + DistanceToEdge + layDateFirst, by = "margin", data = adults.meta, permutations = perms.adult)

Results

Table of all results for fixed and interaction PERMANOVA plus adult

#make df of lmer output
all.bdiv <- as_tibble(rbind(all.adonis.dups.fixed, all.adonis.dups.int, adult.adonis), rownames="Independent variables") %>%
  dplyr::rename("P_estimate"="Pr(>F)") %>% 
  mutate_if(is.numeric, round, 3) %>%
  mutate(P_estimate=ifelse(P_estimate==0,"<0.001",P_estimate)) %>% 
  mutate(P_estimate=ifelse(P_estimate<=0.05,str_c(P_estimate," *"),P_estimate)) %>%
  mutate(P_estimate=ifelse(P_estimate>=0.05 & P_estimate<=0.06,str_c(P_estimate,"  ."),P_estimate))


# make df into kable
## this is in html, dosnt render in word doc # but can copy-paste
all.bdiv.results <- kable(all.bdiv, format = "html", table.attr = "style = \"color: black;\"") %>%
  kableExtra::kable_styling(full_width = F) #%>%
 # kableExtra::group_rows("(a) Top model, proteobacteria",1,nrow(proteobacteria.modelAvg.df)) %>%
  #
  #save_kable("alpha-kable__________.png") # this line saves as .png in Reports/

all.bdiv.results
LS0tCnRpdGxlOiAiSG9zdCBhbmQgRW52aXJvbm1lbnRhbCBkcml2ZXJzIG9mIG1pY3JvYmlvbWU6IEJldGEgZGl2ZXJzaXR5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIHNjcmlwdCBjYXJyaWVzIG91dCB0aGUgYmV0YSBkaXZlcnNpdHkgYW5hbHlzZXMgKGNvbW11bml0eSBjb21wb3NpdGlvbiBhbmQgc3RydWN0dXJlKSBmb3IgdGhlIDIwMTYgQ29yayBncmVhdCB0aXQgbWljcm9iaW9tZSBkYXRhLgoKT3ZlcmFsbCBwbGFuIgoqIG1vZGVsIDE6IGFsbCB2YXJpYWJsZXMgb2YgaW50ZXJlc3QsIG5lc3QgYXMgYmxvY2tpbmcgZmFjdG9yCiogbW9kZWwgMjogYWxsIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCBidXQgYWdlLWhhYml0YXQgaW50ZXJhY3Rpb24sIG5lc3QgYmxvY2tpbmcKKiBtb2RlbCAzOiBhZHVsdCBzYW1wbGVzLCBhbGwgdmFyaWFibGVzIG9mIGludGVyZXN0LCBuZXN0IGJsb2NraW5nCiogdGhlbiBjaGVjayBhcmUgcmVzdWx0cyBkaWZmZXJlbnQgd2hlbiBpbmRpdmlkdWFscyB3LyAyIHNhbXBsZXMgYXJlIGRyb3BwZWQKCkdhYnJpZWxsZSBzYXlzIG5vdCB0byByZW1vdmUgaW5kaXZpZHVhbHMgc2FtcGxlZCB0d2ljZQoKIyBTZXQtdXAgYW5kIGxpYnJhcmllcwoKYGBge3IgSG91c2VrZWVwaW5nLCBlY2hvPUZBTFNFfQpybShsaXN0PWxzKCkpCiNzZXQuc2VlZCgxMCkKYGBgCgoKYGBge3IgU2V0LXVwLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQojIGxpYnJhcmllcwojaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIiwgZGVwZW5kZW5jaWVzID0gVCkKbGlicmFyeSh2ZWdhbikgICMjbm90ZSBoYWQgdHJvdWJsZSBpbnN0YWxsaW5nLCBuZWVkZWQgdG8gaW5zdGFsbCBnZm9ydHJhbiBmaXJzdApsaWJyYXJ5KHRpZHl2ZXJzZSkgIwpsaWJyYXJ5KHBoeWxvc2VxKSAKbGlicmFyeShtaWNyb2Jpb21lKQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGNvbXBvc2l0aW9ucykKbGlicmFyeShnZ2ZvcnRpZnkpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjb3dwbG90KQoKbGlicmFyeShhcm0pCmBgYAoKYGBge3J9CmxpYnJhcnkoZGV2dG9vbHMpCmluc3RhbGxfZ2l0aHViKCJwbWFydGluZXphcmJpenUvcGFpcndpc2VBZG9uaXMvcGFpcndpc2VBZG9uaXMiKQpgYGAKCmBgYHtyIFJlYWQgaW4gZGF0YSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0KcGh5bG8uc3ByaW5nIDwtIHJlYWRSRFMoZmlsZSA9ICIuLi9EYXRhL3BoeWxvLXNwcmluZy5yZHMiKQptZXRhZGF0YSA8LSBtZXRhKHBoeWxvLnNwcmluZykgIyBkb2VzbnQgbWFpbnRhaW4gRGF0ZSBkYXRhLXR5cGUKCnBoeWxvLnNwcmluZwpgYGAKCiMgRGF0YSBjbGVhbmluZwoKUmVtb3ZlIGluZGl2aWR1YWxzIG1lYXN1cmVkIHR3aWNlCiogc2V0LnNlZWQgc28gc2FtZSBpbmRpdmlkdWFscyBkcm9wcGVkCiogbm8gYWR1bHRzIG1lYXN1cmVkIHR3aWNlCmBgYHtyfQojbl9vY2N1ciA8LSBkYXRhLmZyYW1lKHRhYmxlKG1ldGFkYXRhLk5vRHVwcyRiaXJkLklEKSkKI25fb2NjdXJbbl9vY2N1ciRGcmVxID4gMSxdCgpzZXQuc2VlZCgxMTg5KQptZXRhZGF0YS5Ob0R1cHMgPC0gbWV0YWRhdGEgJT4lIAogICAgZ3JvdXBfYnkoYmlyZC5JRCkgJT4lCiAgICBzYW1wbGVfbigxKQoKZHJvcHBlZC5zYW1wbGVzIDwtIHNldGRpZmYobWV0YWRhdGEkQklPTS5JRCwgbWV0YWRhdGEuTm9EdXBzJEJJT00uSUQpCgojIG1ldGFkYXRhLmV2ZW4gPC0gbWV0YWRhdGEgJT4lIAojICAgICBncm91cF9ieShiaXJkLklEKSAlPiUKIyAgICAgc2FtcGxlX24obWluKHRhYmxlKG1ldGFkYXRhJGJpcmQuSUQpKSkKCnRhYmxlKG1ldGFkYXRhJGFnZUJpbm5lZCkKdGFibGUobWV0YWRhdGEuTm9EdXBzJGFnZUJpbm5lZCkKYGBgCgpgYGB7ciBEYXRhIHNwbGl0cywgZWNobz1GQUxTRX0KIyByZWxldmVsIGFnZUJpbm5lZCBmYWN0b3IKbWV0YWRhdGEuTm9EdXBzJGFnZUJpbm5lZCA8LSByZWxldmVsKG1ldGFkYXRhLk5vRHVwcyRhZ2VCaW5uZWQsICIxd2VlayIpCgojIHJlbGV2ZWwgaGFiaXRhdAojbWV0YWRhdGEuTm9EdXBzJGhhYml0YXQgPC0gcmVsZXZlbChtZXRhZGF0YS5Ob0R1cHMkaGFiaXRhdCwgImRlY2lkdW91cyIpCgojICMgc3Vic2V0IHRvIGFkdWx0cwpwaHlsby5hZHVsdHMgPC0gc3Vic2V0X3NhbXBsZXMocGh5bG8uc3ByaW5nLCBhZ2VCaW5uZWQ9PSJhZHVsdCIpCmFkdWx0cy5tZXRhIDwtIG1ldGEocGh5bG8uYWR1bHRzQHNhbV9kYXRhKQoKYGBgCgpEbyBpIG5lZWQgdG8gc2NhbGUgbnVtZXJpYyB2YXJpYWJsZXM/CmBgYHtyfQpudW1lcmljLnByZWRpY3RvcnMgPC0gYygiUXViaXRETkEiLCJUYXJzdXMiLCJXZWlnaHQiLCAid2luZyIsICJicm9vZFNpemVXaGVuU2FtcGxlZCIsICJicm9vZFNpemVNYXgiLCAidG90YWxGbGVkZ2UiLCAiY2x1dGNoU2l6ZSIsICJsYXlEYXRlRmlyc3QiLCAibnVtYmVyRGVhZFByZVJpbmdlZCIsICJudW1iZXJEZWFkUG9zdFJpbmdlZCIsInNjYWxlZC5tYXNzIiwic2NhbGVkLm1hc3Mud2luZy5hZHVsdCIsICJzY2FsZWQubWFzcy50YXJzdXMuYWR1bHQiLCJzY2FsZWQubWFzcy5jaGljayIsICJzY2FsZWQubWFzcy50YXJzdXMiLCAic2NhbGVkLm1hc3Mud2luZyIsICJEaXN0YW5jZVRvRWRnZSIpCgojIGNlbnRyZSBhbmQgc2NhbGUgbnVtZXJpYyB2YXJpYWJsZXMgaWUuIHN1YnRyYWN0IG1lYW4gYW5kIGRpdmlkZSBieSBzdC4gZGV2aWF0aW9uCm1ldGFkYXRhLk5vRHVwcy5zY2FsZWQgPC0gbWV0YWRhdGEuTm9EdXBzCm1ldGFkYXRhLk5vRHVwcy5zY2FsZWRbLG51bWVyaWMucHJlZGljdG9yc10gPC0gc2NhbGUobWV0YWRhdGEuTm9EdXBzLnNjYWxlZFssbnVtZXJpYy5wcmVkaWN0b3JzXSkKCm1ldGFkYXRhLnNjYWxlZCA8LSBtZXRhZGF0YQptZXRhZGF0YS5zY2FsZWRbLG51bWVyaWMucHJlZGljdG9yc10gPC0gc2NhbGUobWV0YWRhdGEuc2NhbGVkWyxudW1lcmljLnByZWRpY3RvcnNdKQoKYWR1bHRzLm1ldGEuc2NhbGVkIDwtIGFkdWx0cy5tZXRhCmFkdWx0cy5tZXRhLnNjYWxlZFssbnVtZXJpYy5wcmVkaWN0b3JzXSA8LSBzY2FsZShhZHVsdHMubWV0YS5zY2FsZWRbLG51bWVyaWMucHJlZGljdG9yc10pCmBgYAoKIyBBbGwgYmlyZHM6IENvRGEsIHcvIGR1cGxpY2F0ZXMKCkNvbXBvc2l0aW9uYWwgbWV0aG9kLCB1c2UgY2xyIHRyYW5zZm9ybQoKS2VlcGluZyByZXBlYXRlZCBtZWFzdXJlcyBoZXJlIGJ1dCB1c2luZyBibG9ja2luZyBmYWN0b3IgdG8gY29udHJvbCBmb3IgcmVwZWF0ZWQgc2FtcGxlcy4gCgpgYGB7cn0KIyBGaWx0ZXIgcmFyZSB0YXhhCnBoeWxvLmtub3dsZXMgPC0gZmlsdGVyX3RheGEocGh5bG8uc3ByaW5nLCBmdW5jdGlvbih4KSBzdW0oeCA+IDEpID4gKDAuMDUqbGVuZ3RoKHgpKSwgVFJVRSkKYGBgCgpgYGB7cn0KIyBwaHlsby5rbm93bGVzLmNsciA8LSBwaHlsby5rbm93bGVzCiMgcGh5bG8ua25vd2xlcy5jbHJAb3R1X3RhYmxlIDwtIG90dV90YWJsZShjbHIocGh5bG8ua25vd2xlc0BvdHVfdGFibGUpLCB0YXhhX2FyZV9yb3dzID0gRikKIyBhaXRjaGlzb24uZGlzdC5kdXBzIDwtIHBoeWxvc2VxOjpkaXN0YW5jZShwaHlsby5rbm93bGVzLmNsciwgbWV0aG9kID0gImV1Y2xpZGVhbiIpCnBrLm90dS5jbHIuZHVwcyA8LSBjbHIocGh5bG8ua25vd2xlc0BvdHVfdGFibGUpCmFpdGNoaXNvbi5kaXN0LmR1cHMgPC0gdmVnZGlzdChway5vdHUuY2xyLmR1cHMsIG1ldGhvZCA9ICJldWNsaWQiKQpgYGAKCmBgYHtyfQojIHBoeWxvLlRTUyA8LSB0cmFuc2Zvcm1fc2FtcGxlX2NvdW50cyhwaHlsby5rbm93bGVzLCBmdW5jdGlvbih4KSB4L3N1bSh4KSkgIyBub3JtYWxpc2UgcmVhZCBjb3VudHMgdy8gVG90YWwtU3VtIFNjYWxpbmcKIyAKIyBCQ2Rpc3QgPC0gcGh5bG9zZXE6OmRpc3RhbmNlKHBoeWxvLlRTUywgbWV0aG9kPSJicmF5IikKYGBgCgpBbGwgdmFyaWFibGVzIGV4Y2VwdCBmb3IgaGFiaXRhdCBoYXZlIGhldGVyb2dlbm91cyBkaXNwZXJzaW9ucwpgYGB7ciwgcmVzdWx0cz0naGlkZScsIHdhcm5pbmc9RkFMU0V9CiMjIEgwPSBObyBkaWZmZXJlbmNlIGluIGRpc3BlcnNpb24gYmV0d2VlbiBncm91cHMKIyBjYWxjIGRpc3BlcnNpb24sIHVzaW5nIGRpc3RhbmNlIG1lYXN1cmUKCnZhcmlhYmxlcyA8LSBjKCJhZ2VCaW5uZWQiLCAiaGFiaXRhdCIsICJsYXlEYXRlRmlyc3QiLCAiYnJvb2RTaXplV2hlblNhbXBsZWQiLCAiRGlzdGFuY2VUb0VkZ2UiLCAiU2VxdWVuY2VQbGF0ZSIpCgpmb3IoaSBpbiB2YXJpYWJsZXMpeyAjIHdvcmtzCiAgZGlzcGVyc2lvbiA8LSBiZXRhZGlzcGVyKGFpdGNoaXNvbi5kaXN0LmR1cHMsIG1ldGFkYXRhLnNjYWxlZFssaV0pICAjLCBiaWFzLmFkanVzdCA9IFQKICBwcmludChpKSAjIHByaW50IHZhcmlhYmxlIGJlaW5nIHRlc3RlZAogIHByaW50KHBlcm11dGVzdChkaXNwZXJzaW9uLCBwYWlyd2lzZT1GQUxTRSwgcGVybXV0YXRpb25zPTEwMDApKQogIGNhdCgiXG4iKSAjIHByaW50IGxpbmUgYnJlYWssIG1ha2VzIGl0IGVhc2llciB0byByZWFkCn0KYGBgCgpgYGB7cn0KI2hpc3QobWV0YWRhdGEkbGF5RGF0ZUZpcnN0KQojaXN0KHNxcnQobWV0YWRhdGEkRGlzdGFuY2VUb0VkZ2UpKQoKZGlzcGVyc2lvbjEgPC0gYmV0YWRpc3BlcihhaXRjaGlzb24uZGlzdC5kdXBzLCBtZXRhZGF0YSRhZ2VCaW5uZWQpICAjLCBiaWFzLmFkanVzdCA9IFQKcHJpbnQocGVybXV0ZXN0KGRpc3BlcnNpb24xLCBwYWlyd2lzZT1GQUxTRSwgcGVybXV0YXRpb25zPTEwMDApKQoKZGlzcGVyc2lvbjIgPC0gYmV0YWRpc3BlcihhaXRjaGlzb24uZGlzdC5kdXBzLCBtZXRhZGF0YSRoYWJpdGF0KSAgIywgYmlhcy5hZGp1c3QgPSBUCnByaW50KHBlcm11dGVzdChkaXNwZXJzaW9uMiwgcGFpcndpc2U9RkFMU0UsIHBlcm11dGF0aW9ucz0xMDAwKSkKCmRpc3BlcnNpb24zIDwtIGJldGFkaXNwZXIoYWl0Y2hpc29uLmRpc3QuZHVwcywgKG1ldGFkYXRhJGxheURhdGVGaXJzdCkpICAjLCBiaWFzLmFkanVzdCA9IFQKcHJpbnQocGVybXV0ZXN0KGRpc3BlcnNpb24zLCBwYWlyd2lzZT1GQUxTRSwgcGVybXV0YXRpb25zPTEwMDApKQoKZGlzcGVyc2lvbjQgPC0gYmV0YWRpc3BlcihhaXRjaGlzb24uZGlzdC5kdXBzLCBtZXRhZGF0YSRicm9vZFNpemVXaGVuU2FtcGxlZCkgICMsIGJpYXMuYWRqdXN0ID0gVApwcmludChwZXJtdXRlc3QoZGlzcGVyc2lvbjQsIHBhaXJ3aXNlPUZBTFNFLCBwZXJtdXRhdGlvbnM9MTAwMCkpCgpkaXNwZXJzaW9uNSA8LSBiZXRhZGlzcGVyKGFpdGNoaXNvbi5kaXN0LmR1cHMsIChtZXRhZGF0YSREaXN0YW5jZVRvRWRnZSkpICAjLCBiaWFzLmFkanVzdCA9IFQKcHJpbnQocGVybXV0ZXN0KGRpc3BlcnNpb241LCBwYWlyd2lzZT1GQUxTRSwgcGVybXV0YXRpb25zPTEwMDApKQoKZGlzcGVyc2lvbjYgPC0gYmV0YWRpc3BlcihhaXRjaGlzb24uZGlzdC5kdXBzLCBtZXRhZGF0YSRTZXF1ZW5jZVBsYXRlKSAgIywgYmlhcy5hZGp1c3QgPSBUCnByaW50KHBlcm11dGVzdChkaXNwZXJzaW9uNiwgcGFpcndpc2U9RkFMU0UsIHBlcm11dGF0aW9ucz0xMDAwKSkKYGBgCgpgYGB7cn0KVHVrZXlIU0QoZGlzcGVyc2lvbjEpClR1a2V5SFNEKGRpc3BlcnNpb24yKQojVHVrZXlIU0QoZGlzcGVyc2lvbjMpCiNUdWtleUhTRChkaXNwZXJzaW9uNCkKI1R1a2V5SFNEKGRpc3BlcnNpb241KQpgYGAKClBsb3QgZGlzcGVyc2lvbnMKYGBge3J9CnBsb3QoZGlzcGVyc2lvbjEpCnBsb3QoZGlzcGVyc2lvbjQpCmBgYAoKYGBge3J9CnBlcm1zLmR1cHMgPC0gd2l0aChtZXRhZGF0YSwgaG93KG5wZXJtID0gMTAwMCwgYmxvY2tzID0gbmVzdCkpCgphbGwuYWRvbmlzLmR1cHMuZml4ZWQgPC0gYWRvbmlzMihhaXRjaGlzb24uZGlzdC5kdXBzIH4gYWdlQmlubmVkICsgaGFiaXRhdCArIGxheURhdGVGaXJzdCArIGJyb29kU2l6ZVdoZW5TYW1wbGVkICsgRGlzdGFuY2VUb0VkZ2UgKyBTZXF1ZW5jZVBsYXRlLCBieT0ibWFyZ2luIiwgbWV0aG9kPSJldWNsaWRpYW4iLCBkYXRhID0gbWV0YWRhdGEuc2NhbGVkLCBwZXJtdXRhdGlvbnMgPSBwZXJtcy5kdXBzKQoKYWxsLmFkb25pcy5kdXBzLmZpeGVkCmBgYAoKYGBge3J9CnBhaXJ3aXNlQWRvbmlzOjpwYWlyd2lzZS5hZG9uaXMyKGFpdGNoaXNvbi5kaXN0LmR1cHMgfiBhZ2VCaW5uZWQgKyBoYWJpdGF0LCBkYXRhID0gbWV0YWRhdGEuc2NhbGVkKQojP3BhaXJ3aXNlLmFkb25pczIoKQpgYGAKClRyeSBzYW1lIGFzIGFib3ZlIGJ1dCBzdHJhdGEgYnkgc2VxdWVuY2UgcGxhdGUgYW5kIHRoZW4gaW5sY3VkZSBpbmRpdmlkdWFsIElECmBgYHtyfQojIHBlcm1zLmR1cHMgPC0gd2l0aChtZXRhZGF0YSwgaG93KG5wZXJtID0gMTAwMCwgYmxvY2tzID0gU2VxdWVuY2VQbGF0ZSkpCiMgCiMgYWxsLmFkb25pcy5kdXBzLmZpeGVkIDwtIGFkb25pczIoYWl0Y2hpc29uLmRpc3QuZHVwcyB+IGFnZUJpbm5lZCArIGhhYml0YXQgKyBsYXlEYXRlRmlyc3QgKyBicm9vZFNpemVXaGVuU2FtcGxlZCArIERpc3RhbmNlVG9FZGdlICsgYmlyZC5JRCwgYnk9Im1hcmdpbiIsIG1ldGhvZD0iZXVjbGlkaWFuIiwgZGF0YSA9IG1ldGFkYXRhLnNjYWxlZCwgcGVybXV0YXRpb25zID0gcGVybXMuZHVwcykKIyAKIyBhbGwuYWRvbmlzLmR1cHMuZml4ZWQKYGBgCgpJbmNsdWRpbmcgYmlyZC5JRCBhcyBhIGZpeGVkIGVmZmVjdCBhbmQgYmxvY2tpbmcgYnkgbmVzdCBzdWdnZXN0cyBhZ2UgaXMgaW4gZmFjdCBhIHNpZ25pZmljYW50IGZhY3RvciB0aG91Z2ggYWNjb3VudHMgZm9yIG9ubHkgMC43JSBvZiB2YXJpYXRpb24sIHdoaWxlIGJpcmQgaWQgYWNjb3VudHMgZm9yIDc1JSwgYnV0IGlzIG5vbi1zaWduaWZpY2FudC4gU2VxdWVuY2UgcGxhdGUgaXMgc2lnbmlmaWNhbnQsIGFjY291bnRpbmcgZm9yIDIuNSUsIGJyb29kIHNpemUgaXMgbm90IHNpZ25pZmljYW50IHdoaWxlIGhhYml0YXQsIGxheSBkYXRlIGFuZCBkaXN0YW5jZSB0byBlZGdlIGNvdWxkIG5vdCBiZSBlc3RpbWF0ZWQuCmBgYHtyfQojIHBlcm1zLmR1cHMgPC0gd2l0aChtZXRhZGF0YSwgaG93KG5wZXJtID0gMTAwMCwgYmxvY2tzID0gbmVzdCkpCiMgCiMgYWxsLmFkb25pcy5kdXBzLmZpeGVkIDwtIGFkb25pczIoYWl0Y2hpc29uLmRpc3QuZHVwcyB+IGFnZUJpbm5lZCArIGhhYml0YXQgKyBsYXlEYXRlRmlyc3QgKyBicm9vZFNpemVXaGVuU2FtcGxlZCArIERpc3RhbmNlVG9FZGdlICsgU2VxdWVuY2VQbGF0ZSArIGJpcmQuSUQsIGJ5PSJtYXJnaW4iLCBtZXRob2Q9ImV1Y2xpZGlhbiIsIGRhdGEgPSBtZXRhZGF0YS5zY2FsZWQsIHBlcm11dGF0aW9ucyA9IHBlcm1zLmR1cHMpCiMgCiMgYWxsLmFkb25pcy5kdXBzLmZpeGVkCmBgYAoKYGBge3J9CiMgcGVybXMuZHVwcyA8LSB3aXRoKG1ldGFkYXRhLCBob3cobnBlcm0gPSAxMDAwLCBibG9ja3MgPSBiaXJkLklEKSkKIyAKIyBhbGwuYWRvbmlzLmR1cHMuZml4ZWQgPC0gYWRvbmlzMihhaXRjaGlzb24uZGlzdC5kdXBzIH4gYWdlQmlubmVkICsgaGFiaXRhdCArIGxheURhdGVGaXJzdCArIGJyb29kU2l6ZVdoZW5TYW1wbGVkICsgRGlzdGFuY2VUb0VkZ2UgKyBTZXF1ZW5jZVBsYXRlLCBieT0ibWFyZ2luIiwgbWV0aG9kPSJldWNsaWRpYW4iLCBkYXRhID0gbWV0YWRhdGEuc2NhbGVkLCBwZXJtdXRhdGlvbnMgPSBwZXJtcy5kdXBzKQojIAojIGFsbC5hZG9uaXMuZHVwcy5maXhlZApgYGAKCgpgYGB7cn0KcGVybXMuZHVwcyA8LSB3aXRoKG1ldGFkYXRhLCBob3cobnBlcm0gPSAxMDAwLCBibG9ja3MgPSBuZXN0KSkKCmFsbC5hZG9uaXMuZHVwcy5pbnQgPC0gYWRvbmlzMihhaXRjaGlzb24uZGlzdC5kdXBzIH4gYWdlQmlubmVkKmhhYml0YXQgKyBsYXlEYXRlRmlyc3QgKyBicm9vZFNpemVXaGVuU2FtcGxlZCArIERpc3RhbmNlVG9FZGdlICsgU2VxdWVuY2VQbGF0ZSwgYnk9Im1hcmdpbiIsIGRhdGEgPSBtZXRhZGF0YS5zY2FsZWQsIHBlcm11dGF0aW9ucyA9IHBlcm1zLmR1cHMpICMKYWxsLmFkb25pcy5kdXBzLmludApgYGAKCkludGVyYWN0aW9uIGNhbGMgYnkgdGVybSByYXRoZXIgdGhhbiBtYXJnaW4gdG8gZ2V0IGVzdGltYXRlcyBmb3IgbWFpbiBlZmZlY3RzIGFzIHdlbGwgYXMgaW50ZXJhY3Rpb24gdGVybQpgYGB7cn0KcGVybXMuZHVwcyA8LSB3aXRoKG1ldGFkYXRhLCBob3cobnBlcm0gPSAxMDAwLCBibG9ja3MgPSBuZXN0KSkKCmFkb25pczIoYWl0Y2hpc29uLmRpc3QuZHVwcyB+IGFnZUJpbm5lZCpoYWJpdGF0ICsgbGF5RGF0ZUZpcnN0ICsgYnJvb2RTaXplV2hlblNhbXBsZWQgKyBEaXN0YW5jZVRvRWRnZSArIFNlcXVlbmNlUGxhdGUsIGJ5PSJ0ZXJtIiwgZGF0YSA9IG1ldGFkYXRhLnNjYWxlZCwgcGVybXV0YXRpb25zID0gcGVybXMuZHVwcykgIwoKYGBgCgojIyBjaGVjayBpbmZsdWVuY2Ugb2YgdW5iYWxhbmNlZCBkZXNpZ24KCmBgYHtyfQp0YWJsZShtZXRhZGF0YSRhZ2VCaW5uZWQsIG1ldGFkYXRhJGhhYml0YXQpCmBgYAoKRm9yIGxvb3Agc2FtcGxlIGVxdWFsIG51bWJlcnMgb2YgZnJvbSBlYWNoIGhhYml0YXQgYW5kIGFnZSBjb21iaW5hdGlvbgpgYGB7cn0KCmBgYAoKIyMgUGxvdCBQQ0EKCmBgYHtyfQphaXRjaC5wY2EgPC0gcHJjb21wKGFpdGNoaXNvbi5kaXN0LmR1cHMpCiNwbG90KGFpdGNoLnBjYSkKYmlwbG90KGFpdGNoLnBjYSkKCmF1dG9wbG90KGFpdGNoLnBjYSwgZGF0YSA9IG1ldGFkYXRhKSMsIGNvbG91ciA9ICJhZ2VCaW5uZWQiLCBsb2FkaW5ncyA9IFQsIGxvYWRpbmdzLmxhYmVsID0gVCwgc2NhbGUgPSAwKQpgYGAKQ29kZSBmcm9tOgpodHRwczovL2h1Ym9xaWFuZy5jbi8yMDE2LzAzLzAzL1JzY2F0dGVyUGxvdFBDQQpgYGB7cn0KZGZfb3V0IDwtIGFzLmRhdGEuZnJhbWUoYWl0Y2gucGNhJHgpCmRmX291dCRhZ2VCaW5uZWQgPC0gbWV0YWRhdGEkYWdlQmlubmVkCmRmX291dCRoYWJpdGF0IDwtIG1ldGFkYXRhJGhhYml0YXQKZGZfb3V0JGxheURhdGVGaXJzdCA8LSBtZXRhZGF0YSRsYXlEYXRlRmlyc3QKZGZfb3V0JGJyb29kU2l6ZVdoZW5TYW1wbGVkIDwtIG1ldGFkYXRhJGJyb29kU2l6ZVdoZW5TYW1wbGVkCgpoZWFkKGRmX291dCkKYGBgCgpDYWxjdWxhdGUgdGhlIFBDIGxvYWRpbmdzIGZvciBsYWJlbHMKKiB0b29rIHRoZXNlIGZyb20gZGlmZmVyZW50IHNpdGVzIGFuZCB0aGV5IGRpc2FncmVlIGFsb3QKYGBge3J9CiMgU3VtIHRoZSB0b3RhbCB2YXJpYW5jZQpkLm12YXIgPC0gc3VtKGFpdGNoLnBjYSRzZGV2XjIpCiMgQ2FsY3VsYXRlIHRoZSBQQzEgYW5kIFBDMiB2YXJpYW5jZQpQQzEubGFiZWwgPC0gcGFzdGUoIlBDMTogIiwgcm91bmQoc3VtKGFpdGNoLnBjYSRzZGV2WzFdXjIpL2QubXZhciwgMykqMTAwLCIlIikKUEMyLmxhYmVsIDwtIHBhc3RlKCJQQzI6ICIsIHJvdW5kKHN1bShhaXRjaC5wY2Ekc2RldlsyXV4yKS9kLm12YXIsIDMpKjEwMCwiJSIpCgojcGVyY2VudGFnZSA8LSByb3VuZChhaXRjaC5wY2Ekc2RldiAvIHN1bShhaXRjaC5wY2Ekc2RldikgKiAxMDAsIDIpCiNwZXJjZW50YWdlIDwtIHBhc3RlKCBjb2xuYW1lcyhkZl9vdXQpLCAiKCIsIHBhc3RlKCBhcy5jaGFyYWN0ZXIocGVyY2VudGFnZSksICIlIiwgIikiLCBzZXA9IiIpICkKCiNzY3JlZXBsb3QoYWl0Y2gucGNhKQpgYGAKClBsb3QKKiBVc2Ugc2FtZSBuYW1lIGFuZCBsYWJlbCBmb3IgZmlsbCBhbmQgc2hhcGUgaW4gb3JkZXIgdG8gb3ZlcmxhcCBsZWdlbmRzCiogZWxsaXBzZSBkZWZhdWx0IGlzIDk1JSBjb25maWRlbmNlIGxldmVsIGZvciB0IGRpc3RyaWJ1dGlvbgoqIGNhbiBkcmF3IGV1Y2xpZCBlbGxpcHNlIHdoZXJlIGxldmVsID0gcmFkaXVzLCBidXQgaG93IHRvIGNob29zZSByYWRpdXM/CiogYWxwaGEgc3BlY2lmaWVzIHRoZSB0cmFuc3BhcmVuY3kKKiBodHRwczovL3N0YXRzLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy8yMTczNzQvcmVhbC1tZWFuaW5nLW9mLWNvbmZpZGVuY2UtZWxsaXBzZQoKYGBge3J9CnAgPC0gZ2dwbG90KGRmX291dCxhZXMoeD1QQzEseT1QQzIsIGNvbG9yPWFnZUJpbm5lZCApKQpwIDwtIHAgKyBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IGhhYml0YXQpKSArIHhsYWIoUEMxLmxhYmVsKSArIHlsYWIoUEMyLmxhYmVsKSAjLCBzaG93LmxlZ2VuZCA9IEYKcCA8LSBwICsgc3RhdF9lbGxpcHNlKGdlb20gPSAicG9seWdvbiIsIHR5cGU9InQiLCBhbHBoYT0wLjEsIAogICAgICAgICAgICAgICAgICAgICAgYWVzKGdyb3VwID0gaW50ZXJhY3Rpb24oYWdlQmlubmVkLCBoYWJpdGF0KSwgZmlsbCA9IGhhYml0YXQsIGNvbG91ciA9IGFnZUJpbm5lZCkpCnAgPC0gcCArIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJIYWJpdGF0IiwgbGFiZWxzID0gYygiQ29uaWZlciIsICJEZWNpZHVvdXMiKSkKcCA8LSBwICsgc2NhbGVfc2hhcGVfZGlzY3JldGUobmFtZSA9ICJIYWJpdGF0IiwgbGFiZWxzID0gYygiQ29uaWZlciIsICJEZWNpZHVvdXMiKSkKcCA8LSBwICsgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9ICJBZ2UiLCBsYWJlbHMgPSBjKCJEYXkgOCIsICJEYXkgMTUiLCAiQWR1bHQiKSkKI3AgPC0gcCArIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKGVsZW1lbnRfYmxhbmsoKSkjLCBsYWJlbHMgPSBOVUxMKQojcCArIGZhY2V0X2dyaWQoaGFiaXRhdH4uKQoKI3RoZW1lPC10aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ib3JkZXI9ZWxlbWVudF9yZWN0KGZpbGw9TkEpLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLHN0cmlwLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRpY2tzPWVsZW1lbnRfbGluZShjb2xvdXI9ImJsYWNrIiksIHBsb3QubWFyZ2luPXVuaXQoYygxLDEsMSwxKSwibGluZSIpKQoKcCt0aGVtZV9jbGFzc2ljKCkKYGBgCgpUcnkgZXVjbGlkaWFuIGVsbGlwc2VzLCBzcGVjaWZ5IHJhZGl1cyB3aXRoIGxldmVsCmBgYHtyfQpwIDwtIGdncGxvdChkZl9vdXQsYWVzKHg9UEMxLHk9UEMyLCBjb2xvcj1hZ2VCaW5uZWQgKSkKcCA8LSBwICsgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBoYWJpdGF0KSkgKyB4bGFiKFBDMS5sYWJlbCkgKyB5bGFiKFBDMi5sYWJlbCkgIywgc2hvdy5sZWdlbmQgPSBGCnAgPC0gcCArIHN0YXRfZWxsaXBzZShnZW9tID0gInBvbHlnb24iLCB0eXBlPSJldWNsaWQiLCBhbHBoYT0wLjEsbGV2ZWwgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGludGVyYWN0aW9uKGFnZUJpbm5lZCwgaGFiaXRhdCksIGZpbGwgPSBoYWJpdGF0LCBjb2xvdXIgPSBhZ2VCaW5uZWQpKQpwIDwtIHAgKyBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiSGFiaXRhdCIsIGxhYmVscyA9IGMoIkNvbmlmZXIiLCAiRGVjaWR1b3VzIikpCnAgPC0gcCArIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKG5hbWUgPSAiSGFiaXRhdCIsIGxhYmVscyA9IGMoIkNvbmlmZXIiLCAiRGVjaWR1b3VzIikpCnAgPC0gcCArIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiQWdlIiwgbGFiZWxzID0gYygiRGF5IDgiLCAiRGF5IDE1IiwgIkFkdWx0IikpCiNwIDwtIHAgKyBzY2FsZV9zaGFwZV9kaXNjcmV0ZShlbGVtZW50X2JsYW5rKCkpIywgbGFiZWxzID0gTlVMTCkKI3AgKyBmYWNldF9ncmlkKGhhYml0YXR+LikKCiN0aGVtZTwtdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYm9yZGVyPWVsZW1lbnRfcmVjdChmaWxsPU5BKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSxzdHJpcC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siKSwgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siKSwgYXhpcy50aWNrcz1lbGVtZW50X2xpbmUoY29sb3VyPSJibGFjayIpLCBwbG90Lm1hcmdpbj11bml0KGMoMSwxLDEsMSksImxpbmUiKSkKCnArdGhlbWVfY2xhc3NpYygpCmBgYAoKYGBge3J9CmZhY2V0LmxhYmVscyA8LSBjKCJDb25pZmVyIiwgIkRlY2lkdW91cyIpCm5hbWVzKGZhY2V0LmxhYmVscykgPC0gYygiY29uaWZlciIsICJkZWNpZHVvdXMiKQpwICsgdGhlbWVfY2xhc3NpYygpICsgZmFjZXRfZ3JpZChoYWJpdGF0fi4sIGxhYmVsbGVyID0gbGFiZWxsZXIoaGFiaXRhdCA9IGZhY2V0LmxhYmVscykpCmBgYAoKYGBge3J9CiMgcGxvdF9vcmRpbmF0aW9uKHBoeWxvLlRTUywgb3JkQkMsIGNvbG9yID0gImFnZUJpbm5lZCIpICsgCiMgICBnZW9tX3BvaW50KHNpemU9MykgKyAKIyAgIGdndGl0bGUoIk9yZDogQnJheS1DdXJ0aXMiKSArIHN0YXRfZWxsaXBzZShnZW9tID0gInBvbHlnb24iLCB0eXBlPSJ0IiwgYWxwaGE9MC4xLCBhZXMoZmlsbD1hZ2VCaW5uZWQpKSsgCiMgICB0aGVtZV9idygpICsgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwgCiMgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJibGFjayIsIHNpemU9LjgpKSArCiMgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQsICBmYW1pbHk9InNlcmlmIiksIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IC43KSkrCiMgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoKQpgYGAKClBsb3QgZmVhdHVyZXMgdGhhdCBjb250cmlidXRlIHRvIGNsYXNzaWZpY2F0aW9uCmBgYHtyfQpkZl9vdXRfciA8LSBhcy5kYXRhLmZyYW1lKGFpdGNoLnBjYSRyb3RhdGlvbikKZGZfb3V0X3IkZmVhdHVyZSA8LSByb3cubmFtZXMoZGZfb3V0X3IpCmRmX291dF9yJGFnZUJpbm5lZCA8LSBtZXRhZGF0YSRhZ2VCaW5uZWQKZGZfb3V0X3IkaGFiaXRhdCA8LSBtZXRhZGF0YSRoYWJpdGF0CmRmX291dF9yJGxheURhdGVGaXJzdCA8LSBtZXRhZGF0YSRsYXlEYXRlRmlyc3QKZGZfb3V0X3IkYnJvb2RTaXplV2hlblNhbXBsZWQgPC0gbWV0YWRhdGEkYnJvb2RTaXplV2hlblNhbXBsZWQKZGZfb3V0X3IkRGlzdGFuY2VUb0VkZ2UgPC0gbWV0YWRhdGEkRGlzdGFuY2VUb0VkZ2UKCgpkZl9vdXRfcgoKcDwtZ2dwbG90KGRmX291dF9yLGFlcyh4PVBDMSx5PVBDMixsYWJlbD1hZ2VCaW5uZWQsY29sb3I9aGFiaXRhdCApKQojcDwtcCtnZW9tX3BvaW50KCkrdGhlbWUgKyBnZW9tX3RleHQoc2l6ZT0zKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKcApgYGAKClBsb3QgCm9uZSBwbG90IGZvciBlYWNoIGhhYml0YXQgKChlbGxpcHNlcyBlYWNoIGFnZSkKKiBjaGFuZ2UgYXBsaGEgdG8gMC4wNT8KYGBge3J9CnAgPC0gZ2dwbG90KGRmX291dCxhZXMoeD1QQzEseT1QQzIsIGNvbG9yPWFnZUJpbm5lZCApKQpwIDwtIHAgKyBnZW9tX3BvaW50KCkgKyB4bGFiKFBDMS5sYWJlbCkgKyB5bGFiKFBDMi5sYWJlbCkgIywgc2hvdy5sZWdlbmQgPSBGCnAgPC0gcCArIHN0YXRfZWxsaXBzZShnZW9tID0gInBvbHlnb24iLCB0eXBlPSJ0IiwgYWxwaGE9MC4xLCAKICAgICAgICAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGludGVyYWN0aW9uKGFnZUJpbm5lZCksIGZpbGwgPSBhZ2VCaW5uZWQsIGNvbG91ciA9IGFnZUJpbm5lZCkpCnAgPC0gcCArIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiQWdlIiwgbGFiZWxzID0gYygiRGF5IDgiLCAiRGF5IDE1IiwgIkFkdWx0IikpCnAgPC0gcCArIHNjYWxlX2ZpbGxfZGlzY3JldGUoZWxlbWVudF9ibGFuaygpLCBsYWJlbHMgPSBOVUxMKQojcCArIGZhY2V0X2dyaWQoaGFiaXRhdH4uKQoKcCt0aGVtZV9jbGFzc2ljKCkKZmFjZXQubGFiZWxzIDwtIGMoIkNvbmlmZXIiLCAiRGVjaWR1b3VzIikKbmFtZXMoZmFjZXQubGFiZWxzKSA8LSBjKCJjb25pZmVyIiwgImRlY2lkdW91cyIpCnAgKyB0aGVtZV9jbGFzc2ljKCkgKyBmYWNldF9ncmlkKGhhYml0YXR+LiwgbGFiZWxsZXIgPSBsYWJlbGxlcihoYWJpdGF0ID0gZmFjZXQubGFiZWxzKSkKYGBgCgpvbmUgcGxvdCBmb3IgZWFjaCBhZ2UgKGVsbGlwc2VzIGVhY2ggaGFiaXRhdCkKYGBge3J9CnAgPC0gZ2dwbG90KGRmX291dCxhZXMoeD1QQzEseT1QQzIsIGNvbG9yPWhhYml0YXQgKSkKcCA8LSBwICsgZ2VvbV9wb2ludCgpICsgeGxhYihQQzEubGFiZWwpICsgeWxhYihQQzIubGFiZWwpICMsIHNob3cubGVnZW5kID0gRgpwIDwtIHAgKyBzdGF0X2VsbGlwc2UoZ2VvbSA9ICJwb2x5Z29uIiwgdHlwZT0idCIsIGFscGhhPTAuMSwgCiAgICAgICAgICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAoaGFiaXRhdCksIGZpbGwgPSBoYWJpdGF0LCBjb2xvdXIgPSBoYWJpdGF0KSkKcCA8LSBwICsgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9ICJIYWJpdGF0IiwgbGFiZWxzID0gYygiQ29uaWZlciIsICJEZWNpZHVvdXMiKSkKcCA8LSBwICsgc2NhbGVfZmlsbF9kaXNjcmV0ZShlbGVtZW50X2JsYW5rKCksIGxhYmVscyA9IE5VTEwpCiNwICsgZmFjZXRfZ3JpZChoYWJpdGF0fi4pCgpwK3RoZW1lX2NsYXNzaWMoKQpmYWNldC5sYWJlbHMgPC0gYygiRGF5IDgiLCAiRGF5IDE1IiwgIkFkdWx0IikKbmFtZXMoZmFjZXQubGFiZWxzKSA8LSBjKCIxd2VlayIsICIyd2VlayIsICJhZHVsdCIpCnAgKyB0aGVtZV9jbGFzc2ljKCkgKyBmYWNldF9ncmlkKGFnZUJpbm5lZH4uLCBsYWJlbGxlciA9IGxhYmVsbGVyKGFnZUJpbm5lZCA9IGZhY2V0LmxhYmVscykpCmBgYAoKIyBKUSByZXF1ZXN0ZWQgcGxvdHMKIyMgZWxsaXBzZXMgZm9yIGp1c3QgYWdlCm9uZSBwbG90IGZvciBlYWNoIGFnZSAoZWxsaXBzZXMgZWFjaCBoYWJpdGF0KQpgYGB7cn0KcCA8LSBnZ3Bsb3QoZGZfb3V0LGFlcyh4PVBDMSx5PVBDMiwgY29sb3I9YWdlQmlubmVkICkpCnAgPC0gcCArIGdlb21fcG9pbnQoKSArIHhsYWIoUEMxLmxhYmVsKSArIHlsYWIoUEMyLmxhYmVsKSAjLCBzaG93LmxlZ2VuZCA9IEYKcCA8LSBwICsgc3RhdF9lbGxpcHNlKGdlb20gPSAicG9seWdvbiIsIHR5cGU9InQiLCBhbHBoYT0wLjEsIAogICAgICAgICAgICAgICAgICAgICAgYWVzKGdyb3VwID0gKGFnZUJpbm5lZCksIGZpbGwgPSBhZ2VCaW5uZWQsIGNvbG91ciA9IGFnZUJpbm5lZCkpCnAgPC0gcCArIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiQWdlIiwgbGFiZWxzID0gYygiRDgiLCAiRDE1IiwgIkFkdWx0IikpCnAgPC0gcCArIHNjYWxlX2ZpbGxfZGlzY3JldGUoZWxlbWVudF9ibGFuaygpLCBsYWJlbHMgPSBOVUxMKQojcCArIGZhY2V0X2dyaWQoaGFiaXRhdH4uKQoKcCt0aGVtZV9jbGFzc2ljKCkKCnAuYWdlIDwtIHAKYGBgCiMjIGVsbGlwc2VzIGZvciBqdXN0IGhhYml0YXQKYGBge3J9CnAgPC0gZ2dwbG90KGRmX291dCxhZXMoeD1QQzEseT1QQzIsIGNvbG9yPWhhYml0YXQgKSkKcCA8LSBwICsgZ2VvbV9wb2ludCgpICsgeGxhYihQQzEubGFiZWwpICsgeWxhYihQQzIubGFiZWwpICMsIHNob3cubGVnZW5kID0gRgpwIDwtIHAgKyBzdGF0X2VsbGlwc2UoZ2VvbSA9ICJwb2x5Z29uIiwgdHlwZT0idCIsIGFscGhhPTAuMSwgCiAgICAgICAgICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAoaGFiaXRhdCksIGZpbGwgPSBoYWJpdGF0LCBjb2xvdXIgPSBoYWJpdGF0KSkKcCA8LSBwICsgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZSA9ICJIYWJpdGF0IiwgbGFiZWxzID0gYygiQ29uaWZlciIsICJEZWNpZHVvdXMiKSkKcCA8LSBwICsgc2NhbGVfZmlsbF9kaXNjcmV0ZShlbGVtZW50X2JsYW5rKCksIGxhYmVscyA9IE5VTEwpCiNwICsgZmFjZXRfZ3JpZChoYWJpdGF0fi4pCgpwK3RoZW1lX2NsYXNzaWMoKQoKcC5oYWJpdGF0IDwtIHAKYGBgCgojIyBDb21iaW5lIGFnZSBhbmQgaGFiaXRhdCBwbG90cwpgYGB7cn0KdGhlbWVfY2xhc3NpYzIgPC0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTIsIGJhc2VfZmFtaWx5ID0gIiIpewogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IGJhc2Vfc2l6ZSwgYmFzZV9mYW1pbHkgPSBiYXNlX2ZhbWlseSkgJStyZXBsYWNlJQogICAgdGhlbWUoCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgcGFuZWwuYm9yZGVyICAgICA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy5saW5lICAgICAgICA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2xpbmUoY29sb3VyPSJncmV5Iiwgc2l6ZT0wLjUsIDMpLAogICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIGxlZ2VuZC5rZXkgICAgICAgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpICMgY2VudHJlIGFuZCBib2xkIHRpdGxlCiAgICApCn0KYGBgCgpgYGB7cn0KcDMgPC0gcGxvdF9ncmlkKHAuYWdlK3RoZW1lX2NsYXNzaWMyKCkrbGFicyh0aXRsZT0iIiksIHAuaGFiaXRhdCt0aGVtZV9jbGFzc2ljMigpK2xhYnModGl0bGU9IiIpLCBuY29sPTIsIGxhYmVscyA9IGMoIkEiLCAiQiIpKQoKYGBgCgojIyBicm9vZCBzaXplCmBgYHtyfQpwIDwtIGdncGxvdChkZl9vdXQsYWVzKHg9UEMxLHk9UEMyLCBjb2xvcj1hcy5mYWN0b3IoYnJvb2RTaXplV2hlblNhbXBsZWQgKSkpCnAgPC0gcCArIGdlb21fcG9pbnQoKSArIHhsYWIoUEMxLmxhYmVsKSArIHlsYWIoUEMyLmxhYmVsKSAjLCBzaG93LmxlZ2VuZCA9IEYKcCA8LSBwICsgc3RhdF9lbGxpcHNlKGdlb20gPSAicG9seWdvbiIsIHR5cGU9InQiLCBhbHBoYT0wLjEsIAogICAgICAgICAgICAgICAgICAgICAgYWVzKGdyb3VwID0gKGFzLmZhY3Rvcihicm9vZFNpemVXaGVuU2FtcGxlZCApKSwgZmlsbCA9IGFzLmZhY3Rvcihicm9vZFNpemVXaGVuU2FtcGxlZCApLCBjb2xvdXIgPSBhcy5mYWN0b3IoYnJvb2RTaXplV2hlblNhbXBsZWQgKSkpCnAgPC0gcCArIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKG5hbWUgPSAiQnJvb2QgU2l6ZSIpCnAgPC0gcCAjKyBzY2FsZV9maWxsX2Rpc2NyZXRlKGVsZW1lbnRfYmxhbmsoKSwgbGFiZWxzID0gTlVMTCkKI3AgKyBmYWNldF9ncmlkKGhhYml0YXR+LikKCnArdGhlbWVfY2xhc3NpYygpCmBgYAoKIyMKYGBge3J9CmVudmZpdDEgPC0gZW52Zml0KGFpdGNoLnBjYX5icm9vZFNpemVXaGVuU2FtcGxlZCwgZGF0YSA9IG1ldGFkYXRhLCBtYWluPSIiLCBjb2w9InJlZCIpCiNwbG90KGFpdGNoLnBjYSwgdHlwZSA9ICJuIikKcGxvdChlbnZmaXQxKQpgYGAKCiMjIFNtb290aCBzdXJmYWNlL3N1cmYgcGxvdApgYGB7cn0Kc3VyZiA8LSBvcmRpc3VyZihhaXRjaC5wY2F+YnJvb2RTaXplV2hlblNhbXBsZWQsIGRhdGEgPSBtZXRhZGF0YSwgbWFpbj0iIiwgY29sPSJyZWQiKQojbWV0YWRhdGEkYnJvb2RTaXplV2hlblNhbXBsZWQKCmhlYWQocm93bmFtZXMobWV0YWRhdGEpKQpoZWFkKGFpdGNoLnBjYSR4KQoKYGBgCgpgYGB7cn0KIyBmcm9tIEplbm55cyBlbWFpbCArIGh0dHBzOi8vY2hyaXNjaGl6aW5za2kuZ2l0aHViLmlvL3JzdGF0cy9vcmRpc3VyZi8Kc3BlY2llcy5zY29yZXMgPC0gYXMuZGF0YS5mcmFtZShzY29yZXMoYWl0Y2gucGNhLCAic3BlY2llcyIpKSAjIGhhdmUgdG8ga2VlcCBzcGVjaWVzIGhlcmUgYXMgdGhlIHRheGEKc3BlY2llcy5zY29yZXMkZ2VudXMgPC0gcm93bmFtZXMoc3BlY2llcy5zY29yZXMpCm5hbWVzKHNwZWNpZXMuc2NvcmVzKVtjKDEsIDIpXSA8LSBjKCJ4IiwgInkiKQpzcGVjaWVzLnNjb3JlcyR6IDwtIE5BCgpkYXRhLnNjb3JlcyA8LSBhcy5kYXRhLmZyYW1lKHNjb3JlcyhkdHJhZHVsdC5tZHMpKQpkYXRhLnNjb3JlcyRiaXJkaWQgPC0gcm93bmFtZXMoZGF0YS5zY29yZXMpCmRhdGEuc2NvcmVzJERldG91cnJlYWNoIDwtIGR0cndpbGQuc3VyZiRkZXRvdXJ3aWxkCmBgYAoKCgpgYGB7cn0KZXh0cmFjdC54eXogPC0gZnVuY3Rpb24ob2JqKSB7CiAgICB4eSA8LSBleHBhbmQuZ3JpZCh4ID0gb2JqJGdyaWQkeCwgeSA9IG9iaiRncmlkJHkpCiAgICB4eXogPC0gY2JpbmQoeHksIGMob2JqJGdyaWQkeikpCiAgICBuYW1lcyh4eXopIDwtIGMoIngiLCAieSIsICJ6IikKICAgIHJldHVybih4eXopCn0KCiNoZWFkKHN1cmYpCmNvbnRvdXIudmFscyA8LSBleHRyYWN0Lnh5eihvYmogPSBzdXJmKQpoZWFkKGNvbnRvdXIudmFscykKYGBgCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGNvbnRvdXIudmFscywgYWVzKHgsIHksIHogPSB6KSkgKyBzdGF0X2NvbnRvdXIoYWVzKGNvbG91ciA9ICkpICsgdGhlbWVfY2xhc3NpYygpCiNjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTEwLCAxMCksIHlsaW0gPSBjKC0xMCwgMTAuNSkpCmBgYAoKaHR0cHM6Ly91c2Vyd2ViLmVuZy5nbGEuYWMudWsvdW1lci5pamF6L2Jpb2luZm9ybWF0aWNzL2Vjb2xvZ2ljYWwuaHRtbApgYGB7cn0KI0dldCBNRFMgc3RhdHMKc29sPC1tZXRhTURTKGFidW5kX3RhYmxlLGRpc3RhbmNlID0gImJyYXkiLCBrID0gMiwgdHJ5bWF4ID0gNTApCiAKI1dlIHVzZSBtZXRhX3RhYmxlJFRlbXAgdG8gcGxvdCB0ZW1wZXJhdHVyZSB2YWx1ZXMgb24gdGhlIHBsb3QuIFlvdSBjYW4gc2VsZWN0CiNhbnkgb3RoZXIgdmFyaWFibGUKIz4gbmFtZXMobWV0YV90YWJsZSkKI1sxXSAicEgiICAgICAgICAgIlRlbXAiICAgICAgICJUUyIgICAgICAgICAiVlMiICAgICAgICAgIlZGQSIgICAgICAgICJDT0R0IiAgICAgIAojWzddICJDT0RzIiAgICAgICAicGVyQ09Ec2J5dCIgIk5INCIgICAgICAgICJQcm90IiAgICAgICAiQ2FyYm8iCiNSZWZlcmVuY2U6aHR0cDovL29saXZpYXJhdGEud29yZHByZXNzLmNvbS8yMDE0LzA3LzE3L29yZGluYXRpb25zLWluLWdncGxvdDItdjItb3JkaXN1cmYvCm9yZGk8LW9yZGlzdXJmKHNvbCxtZXRhX3RhYmxlJFRlbXAscGxvdCA9IEZBTFNFLCBicz0iZHMiKQpvcmRpIDwtIHN1cmYKb3JkaS5ncmlkIDwtIG9yZGkkZ3JpZCAjZXh0cmFjdHMgdGhlIG9yZGlzdXJmIG9iamVjdApzdHIob3JkaS5ncmlkKSAjaXQncyBhIGxpc3QgdGhvdWdoIC0gY2Fubm90IGJlIHBsb3R0ZWQgYXMgaXMKb3JkaS5taXRlIDwtIGV4cGFuZC5ncmlkKHggPSBvcmRpLmdyaWQkeCwgeSA9IG9yZGkuZ3JpZCR5KSAjZ2V0IHggYW5kIHlzCm9yZGkubWl0ZSR6IDwtIGFzLnZlY3RvcihvcmRpLmdyaWQkeikgI3VucmF2ZWwgdGhlIG1hdHJpeCBmb3IgdGhlIHogc2NvcmVzCm9yZGkubWl0ZS5uYSA8LSBkYXRhLmZyYW1lKG5hLm9taXQob3JkaS5taXRlKSkgI2dldHMgcmlkIG9mIHRoZSBuYXMKIApQQ0Ffc3MgPC0gZGF0YS5mcmFtZSh4PWFpdGNoLnBjYSRwb2ludFssMV0seT1haXRjaC5wY2EkcG9pbnRbLDJdLFR5cGU9Z3JvdXBzKQogCnA8LWdncGxvdCgpKwogIHN0YXRfY29udG91cihkYXRhID0gb3JkaS5taXRlLm5hLCBhZXMoeCA9IHgsIHkgPSB5LCB6ID0geiwgY29sb3VyID0gLi5sZXZlbC4uKSxwb3NpdG9uPSJpZGVudGl0eSIpKyAjY2FuIGNoYW5nZSB0aGUgYmlud2lkdGggZGVwZW5kaW5nIG9uIGhvdyBtYW55IGNvbnRvdXJzIHlvdSB3YW50CiAgZ2VvbV9wb2ludChkYXRhPVBDQV9zcyxhZXMoeCx5LGZpbGw9VHlwZSkscGNoPTIxLHNpemU9Myxjb2xvdXI9TkEpCnA8LXArc2NhbGVfY29sb3VyX2NvbnRpbnVvdXMoaGlnaCA9ICJkYXJrZ3JlZW4iLCBsb3cgPSAiZGFya29saXZlZ3JlZW4xIikgI2hlcmUgd2Ugc2V0IHRoZSBoaWdoIGFuZCBsb3cgb2YgdGhlIGNvbG91ciBzY2FsZS4gIENhbiBkZWxldGUgdG8gZ28gYmFjayB0byB0aGUgc3RhbmRhcmQgYmx1ZSwgb3Igc3BlY2lmeSBvdGhlcnMKcDwtcCtsYWJzKGNvbG91ciA9ICJUZW1wZXJhdHVyZSIpICNhbm90aGVyIHdheSB0byBzZXQgdGhlIGxhYmVscywgaW4gdGhpcyBjYXNlLCBmb3IgdGhlIGNvbG91ciBsZWdlbmQKcDwtcCt0aGVtZV9idygpCiNwPC1wK3RoZW1lKGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCksICAjcmVtb3ZlcyB0aGUgYm94IGFyb3VuZCBlYWNoIGxlZ2VuZCBpdGVtCiMgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAjbGVnZW5kIGF0IHRoZSBib3R0b20KIyAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKIyAgICAgICAgICAgICAgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIiwKIyAgICAgICAgICAgICAgbGVnZW5kLmJveC5qdXN0ID0gImNlbnRyZSIpCnAKYGBgCgojIEFkdWx0IGJpcmRzOiBDb0RhCgpBaXRjaGlzb24gZGlzdGFuY2UgaXMgc3VwcG9zZWRseSByb2J1c3QgdG8gc3Vic2V0dGluZy0gY2FuIGkgdGhlcmVmb3JlIGp1c3Qgc3Vic2V0IHRoZSBhZHVsdCBiaXJkcyBmcm9tIHByZXZpb3VzIGRpc3RhbmNlIGNhbGN1bGF0aW9uPwoKYGBge3J9CnBoeWxvLmtuLmFkdWx0IDwtIGZpbHRlcl90YXhhKHBoeWxvLmFkdWx0cywgZnVuY3Rpb24oeCkgc3VtKHggPiAxKSA+ICgwLjA1Kmxlbmd0aCh4KSksIFRSVUUpCgojIHBoeWxvLlRTUy5hZHVsdHMgPC0gdHJhbnNmb3JtX3NhbXBsZV9jb3VudHMocGh5bG8ua24uYWR1bHQsIGZ1bmN0aW9uKHgpIHgvc3VtKHgpKQojIAojIEJDZGlzdC5hZHVsdHMgPC0gcGh5bG9zZXE6OmRpc3RhbmNlKHBoeWxvLlRTUy5hZHVsdHMsIG1ldGhvZD0iYnJheSIpCiMgSkRkaXN0LmFkdWx0cyA8LSBwaHlsb3NlcTo6ZGlzdGFuY2UocGh5bG8uVFNTLmFkdWx0cywgbWV0aG9kPSJqYWNjYXJkIikKYGBgCgpgYGB7cn0KcGsub3R1LmNsci5hZHVsdCA8LSBjbHIocGh5bG8ua24uYWR1bHRAb3R1X3RhYmxlKQphaXRjaGlzb24uZGlzdC5hZHVsdCA8LSB2ZWdkaXN0KHBrLm90dS5jbHIuYWR1bHQsIG1ldGhvZCA9ICJldWNsaWRlYW4iKQpgYGAKCiMjIENoZWNrIGRpc3BlcnNpb24KCkhvbW9nZW5vdXMgZGlzcGVyc2lvbjogc2V4LCBoYWJpdGF0LCBkaXN0YW5jZSBpcyBhbG1vc3Qgbm9uLWhvbW8KTm9uLWhvbW9nZW5vdXM6IGFnZURheXMsIC4uLmFsbCBvdGhlcnMKYGBge3IsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFfQojIyBIMD0gTm8gZGlmZmVyZW5jZSBpbiBkaXNwZXJzaW9uIGJldHdlZW4gZ3JvdXBzCiMgY2FsYyBkaXNwZXJzaW9uLCB1c2luZyBkaXN0YW5jZSBtZWFzdXJlCgp2YXJpYWJsZXMgPC0gYygiYWdlRGF5cyIsICJTZXgiLCAiaGFiaXRhdCIsICJsYXlEYXRlRmlyc3QiLCAiYnJvb2RTaXplV2hlblNhbXBsZWQiLCAiRGlzdGFuY2VUb0VkZ2UiLCAiU2VxdWVuY2VQbGF0ZSIpCgpmb3IoaSBpbiB2YXJpYWJsZXMpeyAjIHdvcmtzCiAgZGlzcGVyc2lvbiA8LSBiZXRhZGlzcGVyKGFpdGNoaXNvbi5kaXN0LmFkdWx0LCBhZHVsdHMubWV0YS5zY2FsZWRbLGldKQogIHByaW50KGkpICMgcHJpbnQgdmFyaWFibGUgYmVpbmcgdGVzdGVkCiAgcHJpbnQocGVybXV0ZXN0KGRpc3BlcnNpb24sIHBhaXJ3aXNlPUZBTFNFLCBwZXJtdXRhdGlvbnM9MTAwMCkpCiAgY2F0KCJcbiIpICMgcHJpbnQgbGluZSBicmVhaywgbWFrZXMgaXQgZWFzaWVyIHRvIHJlYWQKfQoKYGBgCgojIyBNb2RlbGxpbmc6IGFkdWx0IGFpdGNoaXNvbgoKU2V4ICogaGFiaXRhdCAqIGJyb29kU2l6ZVdoZW5TYW1wbGVkICsgU2V4ICogaGFiaXRhdCAqIGxheURhdGVGaXJzdCArIGhhYml0YXQgKiBEaXN0YW5jZVRvRWRnZSArICgxfG5lc3QpICsgKDF8U2VxdWVuY2VQbGF0ZSkKYGBge3J9CnBlcm1zLmFkdWx0IDwtIHdpdGgoYWR1bHRzLm1ldGEsIGhvdyhucGVybSA9IDEwMDAsIGJsb2NrcyA9IG5lc3QpKQoKYWR1bHQuYWRvbmlzIDwtIGFkb25pczIoYWl0Y2hpc29uLmRpc3QuYWR1bHQgfiBhZ2VEYXlzICsgU2V4ICsgaGFiaXRhdCArIERpc3RhbmNlVG9FZGdlICsgbGF5RGF0ZUZpcnN0ICsgYnJvb2RTaXplV2hlblNhbXBsZWQgKyBTZXF1ZW5jZVBsYXRlLCBieSA9ICJtYXJnaW4iLCBkYXRhID0gYWR1bHRzLm1ldGEuc2NhbGVkLCBwZXJtdXRhdGlvbnMgPSBwZXJtcy5hZHVsdCkKYWR1bHQuYWRvbmlzCgojYWRvbmlzMihKRGRpc3QuYWR1bHRzIH4gU2V4ICsgaGFiaXRhdCArIERpc3RhbmNlVG9FZGdlICsgbGF5RGF0ZUZpcnN0LCBieSA9ICJtYXJnaW4iLCBkYXRhID0gYWR1bHRzLm1ldGEsIHBlcm11dGF0aW9ucyA9IHBlcm1zLmFkdWx0KQpgYGAKCiMgUmVzdWx0cwoKVGFibGUgb2YgYWxsIHJlc3VsdHMgZm9yIGZpeGVkIGFuZCBpbnRlcmFjdGlvbiBQRVJNQU5PVkEgcGx1cyBhZHVsdCAKYGBge3J9CiNtYWtlIGRmIG9mIGxtZXIgb3V0cHV0CmFsbC5iZGl2IDwtIGFzX3RpYmJsZShyYmluZChhbGwuYWRvbmlzLmR1cHMuZml4ZWQsIGFsbC5hZG9uaXMuZHVwcy5pbnQsIGFkdWx0LmFkb25pcyksIHJvd25hbWVzPSJJbmRlcGVuZGVudCB2YXJpYWJsZXMiKSAlPiUKICBkcGx5cjo6cmVuYW1lKCJQX2VzdGltYXRlIj0iUHIoPkYpIikgJT4lIAogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMykgJT4lCiAgbXV0YXRlKFBfZXN0aW1hdGU9aWZlbHNlKFBfZXN0aW1hdGU9PTAsIjwwLjAwMSIsUF9lc3RpbWF0ZSkpICU+JSAKICBtdXRhdGUoUF9lc3RpbWF0ZT1pZmVsc2UoUF9lc3RpbWF0ZTw9MC4wNSxzdHJfYyhQX2VzdGltYXRlLCIgKiIpLFBfZXN0aW1hdGUpKSAlPiUKICBtdXRhdGUoUF9lc3RpbWF0ZT1pZmVsc2UoUF9lc3RpbWF0ZT49MC4wNSAmIFBfZXN0aW1hdGU8PTAuMDYsc3RyX2MoUF9lc3RpbWF0ZSwiICAuIiksUF9lc3RpbWF0ZSkpCgoKIyBtYWtlIGRmIGludG8ga2FibGUKIyMgdGhpcyBpcyBpbiBodG1sLCBkb3NudCByZW5kZXIgaW4gd29yZCBkb2MgIyBidXQgY2FuIGNvcHktcGFzdGUKYWxsLmJkaXYucmVzdWx0cyA8LSBrYWJsZShhbGwuYmRpdiwgZm9ybWF0ID0gImh0bWwiLCB0YWJsZS5hdHRyID0gInN0eWxlID0gXCJjb2xvcjogYmxhY2s7XCIiKSAlPiUKICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGKSAjJT4lCiAjIGthYmxlRXh0cmE6Omdyb3VwX3Jvd3MoIihhKSBUb3AgbW9kZWwsIHByb3Rlb2JhY3RlcmlhIiwxLG5yb3cocHJvdGVvYmFjdGVyaWEubW9kZWxBdmcuZGYpKSAlPiUKICAjCiAgI3NhdmVfa2FibGUoImFscGhhLWthYmxlX19fX19fX19fXy5wbmciKSAjIHRoaXMgbGluZSBzYXZlcyBhcyAucG5nIGluIFJlcG9ydHMvCgphbGwuYmRpdi5yZXN1bHRzCmBgYAoK